﻿using Mapster;
using Microsoft.AspNetCore.Mvc;
using RuoVea.DynamicWebApi;
using RuoVea.ExDto;
using RuoVea.ExEnum;
using RuoVea.ExIdGen;
using RuoVea.ExSugar;
using RuoVea.ExSugar.Entity;
using RuoVea.ExUtil;
using RuoVea.OmiApi.Article.Entitys;
using RuoVea.OmiApi.Article.Service.Dto;
using SqlSugar;
using System.ComponentModel;
using exDtoi18n = RuoVea.ExDto.Language.i18n;
using exUtili18n = RuoVea.ExUtil.Language.i18n;

namespace RuoVea.OmiApi.Article.Service;

/// <summary>
/// 文章管理 🔷
/// </summary>
[ApiExplorerSettings(GroupName = "art")]
public class ArticleService : IApplicationService
{
    private readonly SugarRepository<ArtArticle> _thisRepository;
    private readonly SugarRepository<ArtArticleTag> _articleTagRepository;
    private readonly SugarRepository<ArtCategoryArticle> _categoryArticleRepository;
    private readonly ISqlSugarClient _sqlSugarClient;

    /// <summary>
    /// 参数配置表
    /// </summary>
    /// <param name="thisRepository"></param>
    /// <param name="articleTagRepository"></param>
    /// <param name="categoryArticleRepository"></param>
    /// <param name="sqlSugarClient"></param>
    public ArticleService(SugarRepository<ArtArticle> thisRepository, SugarRepository<ArtArticleTag> articleTagRepository, SugarRepository<ArtCategoryArticle> categoryArticleRepository, ISqlSugarClient sqlSugarClient)
    {
        _thisRepository = thisRepository;
        _articleTagRepository = articleTagRepository;
        _categoryArticleRepository = categoryArticleRepository;
        _sqlSugarClient = sqlSugarClient;
    }

    /// <summary>
    /// 查询所有/分页🔹
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public virtual async Task<PageResult<ArtArticleOutDto>> GetPagesAsync([FromQuery] ArticleParam data)
    {
        var query = _thisRepository.AsQueryable()
            .Includes(u => u.Categories)
            .Includes(u => u.Tags)
            .Includes(u => u.Seo)
            .WhereIF(data.Title.NotNullOrWhiteSpace(), u => u.Title.Contains(data.Title))
            .WhereIF(data.UserId > 0, u => u.Creator == data.UserId)
            .WhereIF(data.Status != null, u => u.Status == data.Status)
            .WhereIF(data.IsTop != null, u => u.IsTop == data.IsTop)
            .WhereIF(data.IsFeatured != null, u => u.IsFeatured == data.IsFeatured)
            .WhereIF(data.IsCommentAllowed != null, u => u.IsCommentAllowed == data.IsCommentAllowed);

        // 使用子查询方式，避免复杂的连表参数问题
        if (data.CategorieIds != null && data.CategorieIds.Any())
        {
            query = query.Where(u => u.Categories.Any(c => data.CategorieIds.Contains(c.Id)));
        }

        if (data.CategorieIsDisable != null)
        {
            query = query.Where(u => u.Categories.Any(c => c.IsDisable == data.CategorieIsDisable));
        }

        if (data.TagIds != null && data.TagIds.Any())
        {
            query = query.Where(u => u.Tags.Any(t => data.TagIds.Contains(t.Id)));
        }

        var result = await query
            .OrderByDescending(u => u.CreateTime)
            .OrderBy(u => u.Sort)
            .ToPageAsync<ArtArticle, ArtArticleOutDto>(data.PageNo, data.PageSize);

        return result;
    }

    /// <summary>
    /// 获取分类启用状态的文章分页列表
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public virtual async Task<PageResult<ArtArticleOutDto>> GetPagesEnableAsync([FromQuery] ArticleParam data)
    {
        data.CategorieIsDisable = YesOrNot.N;
        return await GetPagesAsync(data);
    }

    /// <summary>
    /// 获取分类启用状态且文章已发布文章分页列表
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public virtual async Task<PageResult<ArtArticleOutDto>> GetPagesPushsAsync([FromQuery] ArticleParam data)
    {
        data.CategorieIsDisable = YesOrNot.N;
        data.Status = 1;
        return await GetPagesAsync(data);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="pageNo"></param>
    /// <param name="pageSize"></param>
    /// <param name="categoryIds"></param>
    /// <returns></returns>
    public virtual async Task<PageResult<ArtArticleOutDto>> GetPagesByCategorysAsync(int pageNo = 1,int pageSize = 10, List<long> categoryIds = null)
    {
        return await GetPagesPushsAsync(new ArticleParam {PageNo = pageNo, PageSize = pageSize,CategorieIds=categoryIds  });
    }
    
    /// <summary>
    /// 
    /// </summary>
    /// <param name="pageNo"></param>
    /// <param name="pageSize"></param>
    /// <param name="tagIds"></param>
    /// <returns></returns>
    public virtual async Task<PageResult<ArtArticleOutDto>> GetPagesByTagsAsync(int pageNo = 1, int pageSize = 10, List<long> tagIds = null)
    {
        return await GetPagesPushsAsync(new ArticleParam { PageNo = pageNo, PageSize = pageSize, TagIds = tagIds });
    }

    /// <summary>
    /// 获取列表🔹
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取列表")]
    public List<ArticleOutputDto> GetList(ArticleParam data)
    {
        var query = _thisRepository.AsQueryable()
            .WhereIF(data.Title.NotNullOrWhiteSpace(), u => u.Title.Contains(data.Title))
            .WhereIF(data.UserId > 0, u => u.Creator == data.UserId)
            .WhereIF(data.Status != null, u => u.Status == data.Status)
            .WhereIF(data.IsTop != null, u => u.IsTop == data.IsTop)
            .WhereIF(data.IsFeatured != null, u => u.IsFeatured == data.IsFeatured)
            .WhereIF(data.IsCommentAllowed != null, u => u.IsCommentAllowed == data.IsCommentAllowed)
            .OrderByDescending(u => u.CreateTime)
            .OrderBy(u => u.Sort);
        // 标签过滤
        if (data.TagIds != null && data.TagIds.Any())
        {
            var articleIdsWithTags = _articleTagRepository.AsQueryable()
                .Where(t => data.TagIds.Contains(t.TagId))
                .Select(t => t.ArticleId).ToList();
            query = query.Where(u => articleIdsWithTags.Contains(u.Id));
        }

        // 分类过滤
        if (data.CategorieIds != null && data.CategorieIds.Any())
        {
            var articleIdsWithCategories = _categoryArticleRepository
                .AsQueryable()
                .InnerJoin<ArtCategory>((u, c) => u.CategoryId == c.Id)
                .Where((u, c) => data.CategorieIds.Contains(u.CategoryId))
                .WhereIF(data.CategorieIsDisable != null, (u, c) => c.IsDisable == data.CategorieIsDisable)
                .Select(c => c.ArticleId).ToList();
            query = query.Where(u => articleIdsWithCategories.Contains(u.Id));
        }

        var result = query.Select(u => new ArticleOutputDto
        {
            Id = u.Id,
            Title = u.Title,
            Subtitle = u.Subtitle,
            Summary = u.Summary,
            CoverImage = u.CoverImage
        }).ToPageList(data.PageNo, data.PageSize);
        return result;
    }

    /// <summary>
    /// 获取分类可用列表🔹
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取列表")]
    public List<ArticleOutputDto> GetEnableList(ArticleParam data)
    {
        data.CategorieIsDisable = YesOrNot.N;
        return GetList(data);
    }

    /// <summary>
    /// 根据主键查询🔹
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public virtual async Task<ArtArticleOutDto> GetDataAsync([FromQuery] EntityBaseId data)
    {
        if (data == null)
            throw new ArgumentException(ErrorEnum.D1504.GetDescription(exDtoi18n.ResourceManager));

        var model = await _thisRepository.AsQueryable()
            .Includes(u => u.Categories)
            .Includes(a => a.Tags)
            .Includes(a => a.Seo)
            .Where(x => x.Id == data.Id)
            .FirstAsync();
        return model.Adapt<ArtArticleOutDto>();
    }

    /// <summary>
    /// 根据主键查询🔹
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual async Task<ArtArticleOutDto> GetDataByIdAsync([FromQuery] long id)
    {
        return await GetDataAsync(new EntityBaseId { Id=id });
    }

    /// <summary>
    /// 增加阅读量
    /// </summary>
    /// <returns></returns>
    public async Task<bool> PlusViewCountByIdAsync(long id)
    {
        return await PlusViewCountAsync(new EntityBaseId { Id = id });
    }

    /// <summary>
    /// 增加阅读量
    /// </summary>
    /// <returns></returns>
    public async Task<bool> PlusViewCountAsync([FromBody] EntityBaseId data)
    {
        if (data == null)
            throw new ArgumentException(ErrorEnum.D1504.GetDescription(exDtoi18n.ResourceManager));

        data.Check();
        var result = await _thisRepository.Context.Updateable<ArtArticle>()
                  .SetColumns(a => a.ViewCount == a.ViewCount + 1)
                  .Where(a => a.Id == data.Id)
                  .ExecuteCommandAsync() > 0;
        return result;
    }

    /// <summary>
    /// 添加🔹
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public virtual async Task<bool> AddDataAsync([FromBody] ArticleDto data)
    {
        if (data == null)
            throw new ArgumentException(ErrorEnum.D1504.GetDescription(exDtoi18n.ResourceManager));

        if (data.Title.IsNullOrWhiteSpace())
            throw new AggregateException(string.Format(exUtili18n.fieldisrequired, "Title"));

        if (data.Content.IsNullOrWhiteSpace())
            throw new AggregateException(string.Format(exUtili18n.fieldisrequired, "Content"));

        if (data.Categories.Any() == false)
            throw new AggregateException(string.Format(exUtili18n.fieldisrequired, "Categories"));

        var article = data.Adapt<ArtArticle>();

        article.Id = IdGenerator.Id;

        long newArticleId = article.Id;

        var result = await _sqlSugarClient.Ado.UseTranAsync(async () =>
        {
            await _thisRepository.InsertAsync(article);

            // 处理分类
            if (data.Categories.Any())
            {
                List<ArtCategoryArticle> categoryArticles = data.Categories
                    .Select(x => new ArtCategoryArticle { CategoryId = x, ArticleId = newArticleId })
                    .ToList();
                await _sqlSugarClient.Insertable(categoryArticles).ExecuteCommandAsync();
            }

            // 处理标签
            if (data.Tags.Any())
            {
                List<ArtArticleTag> articleTags = data.Tags
                .Select(x => new ArtArticleTag { TagId = x, ArticleId = newArticleId })
                .ToList();

                await _sqlSugarClient.Insertable(articleTags).ExecuteCommandAsync();
            }

            // 处理SEO
            if (data.Seo != null)
            {
                ArtSeo artSeo = new()
                {
                    Id = IdGenerator.Id,
                    ArticleId = newArticleId,
                    MetaTitle = data.Seo.MetaTitle,
                    CanonicalUrl = data.Seo.CanonicalUrl,
                    MetaKeywords = data.Seo.MetaKeywords,
                    MetaDescription = data.Seo.MetaDescription
                };

                await _sqlSugarClient.Insertable(artSeo).ExecuteCommandAsync();
            }
        });

        if (!result.IsSuccess)
            throw new ArgumentException(result.ErrorMessage);

        return result.IsSuccess;
    }

    /// <summary>
    /// 修改🔹
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns> 
    public virtual async Task UpdateDataAsync([FromBody] ArticleDto data)
    {
        if (data == null)
            throw new ArgumentException(ErrorEnum.D1504.GetDescription(exDtoi18n.ResourceManager));

        if (data.Id <= 0)
            throw new AggregateException(string.Format(exUtili18n.invalidintegerformat, "Id"));

        if (data.Title.IsNullOrWhiteSpace())
            throw new AggregateException(string.Format(exUtili18n.fieldisrequired, "Title"));

        if (data.Content.IsNullOrWhiteSpace())
            throw new AggregateException(string.Format(exUtili18n.fieldisrequired, "Content"));

        if (data.Categories.Any() == false)
            throw new AggregateException(string.Format(exUtili18n.fieldisrequired, "Categories"));

        var isExist = await _thisRepository.IsAnyAsync(u => u.Id == data.Id);
        if (!isExist) throw new ArgumentException(ErrorEnum.D1002.GetDescription(exDtoi18n.ResourceManager));

        var article = data.Adapt<ArtArticle>();

        var result = await _sqlSugarClient.Ado.UseTranAsync(async () =>
        {
            // 更新文章主表
            await _thisRepository.UpdateAsync(article);

            // 处理分类
            if (data.Categories.Any())
            {
                // 删除原有分类关联
                int categoryArticleDelete = await _sqlSugarClient.Deleteable<ArtCategoryArticle>()
                    .Where(x => x.ArticleId == data.Id)
                    .ExecuteCommandAsync();

                // 添加新的分类关联
                List<ArtCategoryArticle> categoryArticles = data.Categories
                    .Select(x => new ArtCategoryArticle { CategoryId = x, ArticleId = data.Id })
                    .ToList();
                var t = await _sqlSugarClient.Insertable(categoryArticles).IgnoreColumns(x => x.Id).ExecuteCommandAsync();
            }

            // 处理标签
            if (data.Tags.Any())
            {
                // 删除原有标签关联
                await _sqlSugarClient.Deleteable<ArtArticleTag>()
                    .Where(x => x.ArticleId == data.Id)
                    .ExecuteCommandAsync();

                // 添加新的标签关联
                List<ArtArticleTag> articleTags = data.Tags
                    .Select(x => new ArtArticleTag { TagId = x, ArticleId = data.Id })
                    .ToList();
                await _sqlSugarClient.Insertable(articleTags).IgnoreColumns(x => x.Id).ExecuteCommandAsync();
            }

            // 处理SEO
            if (data.Seo != null)
            {
                // 先尝试更新，如果不存在则插入
                var existingSeo = await _sqlSugarClient.Queryable<ArtSeo>()
                    .Where(x => x.ArticleId == data.Id)
                    .FirstAsync();

                if (existingSeo != null)
                {
                    await _sqlSugarClient.Updateable<ArtSeo>()
                        .SetColumns(it => new ArtSeo()
                        {
                            MetaTitle = data.Seo.MetaTitle,
                            CanonicalUrl = data.Seo.CanonicalUrl,
                            MetaKeywords = data.Seo.MetaKeywords,
                            MetaDescription = data.Seo.MetaDescription
                        })
                        .Where(it => it.ArticleId == data.Id) // 添加WHERE条件
                        .ExecuteCommandAsync();
                }
                else
                {
                    ArtSeo artSeo = new()
                    {
                        Id = IdGenerator.Id,
                        ArticleId = data.Id,
                        MetaTitle = data.Seo.MetaTitle,
                        CanonicalUrl = data.Seo.CanonicalUrl,
                        MetaKeywords = data.Seo.MetaKeywords,
                        MetaDescription = data.Seo.MetaDescription
                    };

                    await _sqlSugarClient.Insertable(artSeo).ExecuteCommandAsync();
                }
            }

            return true;
        });

        if (!result.IsSuccess)
        {
            throw new Exception(result.ErrorMessage);
        }
    }

    /// <summary>
    /// 删除🔹
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    [HttpDelete]
    public virtual async Task DeleteDataAsync([FromBody] EntityBaseId data)
    {
        data.Check();

        var article = await _thisRepository.GetFirstAsync(u => u.Id == data.Id);
        if (article == null)
            throw new ArgumentException(ErrorEnum.D1002.GetDescription(exDtoi18n.ResourceManager));

        // 使用事务处理所有删除操作
        var result = await _sqlSugarClient.Ado.UseTranAsync(async () =>
        {
            if (article.IsDelete == IsDelete.Y)
            {
                // 物理删除（如果已经是删除状态）
                await _thisRepository.DeleteByIdAsync(data.Id);

                // 删除关联的分类关系
                await _sqlSugarClient.Deleteable<ArtCategoryArticle>()
                    .Where(x => x.ArticleId == data.Id)
                    .ExecuteCommandAsync();

                // 删除关联的标签关系
                await _sqlSugarClient.Deleteable<ArtArticleTag>()
                    .Where(x => x.ArticleId == data.Id)
                    .ExecuteCommandAsync();

                // 删除关联的SEO数据
                await _sqlSugarClient.Deleteable<ArtSeo>()
                    .Where(x => x.ArticleId == data.Id)
                    .ExecuteCommandAsync();
            }
            else
            {
                // 软删除
                article.IsDelete = IsDelete.Y;
                await _thisRepository.UpdateAsync(article);

                // 注意：软删除时通常不删除关联数据，保持数据完整性
                // 如果需要同时软删除关联数据，可以在这里添加相应逻辑
            }
        });

        if (!result.IsSuccess)
        {
            throw new Exception(result.ErrorMessage);
        }
    }



}
